using Game.Networking;
using Game.Networking.Server;
using MemoryPack;
using NaughtyAttributes;
using System.Collections.Generic;
using UnityEngine;

namespace Game {
	public class TeamBase : WorldEntity<TeamBaseState> {
		public float     CargoGrabDistance = 25f;
		public float     GrabInterval = 2f;
		public Transform SpawnPoint;
		public float     SpawnRadius = 4.3f;
		public int       HealthRestorePerTick = 2;
		public int       MaxHealth = 100;
		public int       MaxSignalCount = 10;

		List<ShipSignal> _shipSignals = new List<ShipSignal>();

		public override EntityType EntityType => EntityType.TeamBase;

		[ShowNativeProperty]
		public uint Score => _score;

		TeamType _team;
		uint     _score;
		uint    _lastSignalId;

		float _lastGrabTime = 0f;
		Collider[]            _tmpColliderArray = new Collider[64];
		List<CargoContainer> _tmpContainers = new List<CargoContainer>(16);

		[ShowNativeProperty]
		public TeamType Team {
			get {
				return _team;
			}
			set {
				_team = value;
				GetComponentInChildren<TeamSkin>()?.SetTeamColor(value);
			}
		}

		private void Update() {
			if ( IsServer &&  Time.time - _lastGrabTime > GrabInterval) {
				TryGrabCargo();
				_lastGrabTime = Time.time;
			}
		}

		public Vector3 GetNewSpawnPos() {
			return SpawnPoint.position + Random.insideUnitSphere* SpawnRadius;
		}

		public void AddScore(uint score) {
			_score += score;
		}

		void TryGrabCargo() {
			GetNearbyGrabbableItems();
			if ( _tmpContainers.Count == 0 ) {
				return;
			}
			for ( int i = 0; i < _tmpContainers.Count; i++ ) {
				var container = _tmpContainers[i];
				var creator = container.CreatorID;
				var price = container.GetTotalPrice();
				if ( price > 0 ) {
					_score += (uint)price;
				}
				ServerAgentsController.Instance.AddScoreToAgentOwner(creator, (uint)price);
				_tmpContainers[i].FakeCollect(transform.position);
			}
		}

		void GetNearbyGrabbableItems() {
			_tmpContainers.Clear();
			var count = Physics.OverlapSphereNonAlloc(transform.position, CargoGrabDistance, _tmpColliderArray, CommonStaticData.Instance.DynamicEntitiesMask);
			for ( int i = 0; i < count; i++ ) {
				var cargo = _tmpColliderArray[i].GetComponent<CargoContainer>();
				if ( cargo ) {
					_tmpContainers.Add(cargo);
					continue;
				}
				var ship = _tmpColliderArray[i].GetComponent<ShipCore>();
				if ( ship && ship.Team == Team ) {
					if ( ship.Health < MaxHealth ) {
						ship.Health += HealthRestorePerTick;
						if ( ship .Health > MaxHealth ) {
							ship.Health = MaxHealth;
						}
					}
				}
			}
		}

		public override void ApplyFullState(EntityState state) {
			base.ApplyFullState(state);
			var cast = (TeamBaseState)state;
			if ( cast == null ) {
				return;
			}
			Team = cast.Team;
			_score= cast.Score;
			_lastSignalId = cast.LastSignalId;
			_shipSignals = cast.ShipSignalQueue;
		}

		protected override TeamBaseState SaveInternal() {
			var s = base.SaveInternal();
			s.Team = Team;
			s.Score = Score;
			s.LastSignalId = _lastSignalId;
			s.ShipSignalQueue = _shipSignals;
			return s;
		}

		protected override string CreateSummary() {
			return $"type:base,team:{Team}";
		}

		public void SendSignal(uint shipId, ShipSignalType type, Vector3 position) {
			var signalId = GetNewSignalId();
			var signal = new ShipSignal() {
				CallerId = shipId,
				SignalType = type,
				Position = position,
				SignalID = signalId
			};
			_shipSignals.Add(signal);
			if ( _shipSignals.Count > MaxSignalCount) {
				_shipSignals.RemoveAt(0);
			}
		}

		public uint LastSignalId() {
			return _lastSignalId;
		}

		public ShipSignal ReadSignal(uint lastReceivedSignalId) {
			foreach ( var item in _shipSignals ) {
				if ( item.SignalID > lastReceivedSignalId) {
					return item;
				}
			}
			return default;
		}

		uint GetNewSignalId() {
			_lastSignalId++;
			return _lastSignalId;
		}
	}

	[MemoryPackable]
	public partial class TeamBaseState : WorldEntityState {
		public TeamType Team;
		public uint     Score;
		public uint		LastSignalId;
		public List<ShipSignal> ShipSignalQueue = new List<ShipSignal>();
	}
}
